"""
五子棋游戏逻辑模块

实现五子棋游戏的核心逻辑，包括棋盘操作、落子规则、胜负判断等。
这是游戏功能的核心组件，不依赖外部资源。
"""

from typing import List, Optional, Tuple, Dict, Any
import json

from app.modules.gomoku.config import settings


class GomokuLogic:
    """
    五子棋游戏逻辑类
    
    提供棋盘操作、判断胜负等核心功能。
    """
    
    def __init__(self, board_size: int = settings.BOARD_SIZE):
        """
        初始化游戏逻辑
        
        Args:
            board_size: 棋盘大小，默认15x15
        """
        self.board_size = board_size
        self.directions = [
            (1, 0),   # 水平方向
            (0, 1),   # 垂直方向
            (1, 1),   # 右下对角线
            (1, -1),  # 右上对角线
        ]
    
    def create_empty_board(self) -> List[List[Optional[str]]]:
        """
        创建空棋盘
        
        Returns:
            二维数组表示的空棋盘
        """
        return [[None for _ in range(self.board_size)] for _ in range(self.board_size)]
    
    def is_valid_move(
        self, board: List[List[Optional[str]]], x: int, y: int
    ) -> bool:
        """
        检查落子是否有效
        
        Args:
            board: 当前棋盘状态
            x: 横坐标
            y: 纵坐标
            
        Returns:
            布尔值，表示落子是否有效
        """
        # 检查坐标是否在棋盘范围内
        if x < 0 or x >= self.board_size or y < 0 or y >= self.board_size:
            return False
        
        # 检查位置是否已被占用
        if board[y][x] is not None:
            return False
        
        return True
    
    def make_move(
        self, board: List[List[Optional[str]]], x: int, y: int, color: str
    ) -> List[List[Optional[str]]]:
        """
        在棋盘上落子
        
        Args:
            board: 当前棋盘状态
            x: 横坐标
            y: 纵坐标
            color: 棋子颜色 ('black' 或 'white')
            
        Returns:
            更新后的棋盘
            
        Raises:
            ValueError: 如果落子无效
        """
        if not self.is_valid_move(board, x, y):
            raise ValueError(f"无效的落子位置: ({x}, {y})")
        
        # 创建棋盘的副本
        new_board = [row[:] for row in board]
        new_board[y][x] = color
        
        return new_board
    
    def count_in_direction(
        self, board: List[List[Optional[str]]], x: int, y: int, 
        dx: int, dy: int, color: str
    ) -> int:
        """
        计算某个方向上连续相同颜色的棋子数量
        
        Args:
            board: 当前棋盘状态
            x, y: 起始坐标
            dx, dy: 方向向量
            color: 棋子颜色
            
        Returns:
            连续相同颜色的棋子数量
        """
        count = 0
        current_x, current_y = x, y
        
        # 从起始位置沿着指定方向计数
        while (0 <= current_x < self.board_size and 
               0 <= current_y < self.board_size and 
               board[current_y][current_x] == color):
            count += 1
            current_x += dx
            current_y += dy
        
        return count
    
    def check_win(
        self, board: List[List[Optional[str]]], x: int, y: int, color: str
    ) -> bool:
        """
        检查指定位置的落子是否导致游戏获胜
        
        Args:
            board: 当前棋盘状态
            x, y: 最后落子的坐标
            color: 棋子颜色
            
        Returns:
            布尔值，表示是否获胜
        """
        for dx, dy in self.directions:
            # 正向计数
            count1 = self.count_in_direction(board, x, y, dx, dy, color)
            # 反向计数（减1避免重复计算当前位置）
            count2 = self.count_in_direction(board, x, y, -dx, -dy, color) - 1
            
            # 总计数
            total = count1 + count2
            
            # 五子连珠获胜
            if total >= settings.WIN_CONDITION:
                return True
        
        return False
    
    def is_board_full(self, board: List[List[Optional[str]]]) -> bool:
        """
        检查棋盘是否已满
        
        Args:
            board: 当前棋盘状态
            
        Returns:
            布尔值，表示棋盘是否已满
        """
        for row in board:
            for cell in row:
                if cell is None:
                    return False
        return True
    
    def parse_board_state(self, board_state_json: str) -> Dict[str, Any]:
        """
        解析JSON格式的棋盘状态
        
        Args:
            board_state_json: JSON字符串表示的棋盘状态
            
        Returns:
            解析后的棋盘状态对象
        """
        try:
            return json.loads(board_state_json)
        except json.JSONDecodeError:
            # 解析失败，返回默认空棋盘
            return {
                "size": self.board_size,
                "board": self.create_empty_board(),
                "last_move": None
            }
    
    def serialize_board_state(self, board_state: Dict[str, Any]) -> str:
        """
        将棋盘状态序列化为JSON字符串
        
        Args:
            board_state: 棋盘状态对象
            
        Returns:
            JSON字符串表示的棋盘状态
        """
        return json.dumps(board_state)


# 创建单例实例
gomoku_logic = GomokuLogic() 